#include "PrecompiledHeaders.h"
#include "PickupControl.h"
#include "Constants.h"
#include "Ball.h"

// TODO: - time limit does not work
//       - sort out animations
//       - cloning

OgreNewt::MaterialPair *PickupControl::ball_mat_pair = NULL;

PickupControl::PickupControl(std::vector<Pickup*> *pi, OgreNewt::World *w)
{
    world = w;
    time = 0;
    pickups = pi;
    
    std::vector<Pickup*>::iterator it;
    for(it = pickups->begin(); it != pickups->end(); it++) {
        PickupState ps;
        ps.state = PU_INACTIVE;
        ps.update_time = -1;
        pickup_states.push_back(ps);
    }
}

PickupControl::~PickupControl(void) {}

void PickupControl::reset()
{
    active_pickups.clear();

    std::vector<PickupState>::iterator it;
    int i = 0;
    for(it = pickup_states.begin(); it != pickup_states.end(); ++it , ++i)
    {
        if (it->state == PU_ACTIVE)
        {
            try {
                PowerUp *pu = dynamic_cast<PowerUp*>(pickups->at(i));
                if (pu) pu->undo(player);
            } catch (std::exception e) {}
        }
        it->state = PU_INACTIVE;
    }
    
    if (player->isMainPlayer())
    {
        std::vector<Pickup*>::iterator j;
        for(j = pickups->begin(); j != pickups->end(); ++j)
            (*j)->reset();
    }
}

void PickupControl::setRespawnTime(Ogre::String name, Ogre::Real r)
{
/*
    std::map<Ogre::String, Pickup>::iterator it;
    it = pickups.find(name);
    if (it == pickups.end())
        throw new Ogre::Exception(13001, "No pickup with name of '" + name + "' exists", "PickupControl::setRespawn");
    else {
        it->second.respawn = true;
        it->second.respawn_time = r;
    }
*/
}
void PickupControl::setActiveTime(Ogre::String name, Ogre::Real t)
{
/*
    std::map<Ogre::String, Pickup>::iterator it;
    it = pickups.find(name);
    if (it == pickups.end())
        throw new Ogre::Exception(13001, "No pickup with name of '" + name + "' exists", "PickupControl::setActiveTime");
    else
        it->second.active_time = t;
*/
}

bool PickupControl::frameStarted(Ogre::Real t)
{
    // animate pickups
    if (player->isMainPlayer()) {
        std::vector<Pickup*>::iterator i;
        for(i = pickups->begin(); i != pickups->end(); ++i) {
            (*i)->animate(t);
        }
    }
    
    time += t;
    std::list<unsigned>::iterator j;
    for (j = active_pickups.begin(); j != active_pickups.end(); j++) {
        if (*j < pickup_states.size()) {
            std::vector<PickupState>::iterator it = pickup_states.begin() + *j;
            if (time >= it->update_time) {
                Pickup *p = pickups->at(*j);
                PowerUp *pu = dynamic_cast<PowerUp*>(p);
                if (it->state == PU_ACTIVE) {
                    it->state = PU_EXPIRED;
                    if (pu) {
                        pu->undo(player);
                        if (pu->respawn) {
                            it->update_time = time + pu->respawn_time;
                            break; // don't remove from active pickups
                        }
                    }
                } else if (it->state == PU_EXPIRED) {
                    it->state = PU_INACTIVE;
                    p->reset();
                }
                std::list<unsigned>::iterator e = j++;
                active_pickups.erase(e);
                if (j == active_pickups.end())
                    break;
            }
        }
    }
    
    return true;
}

void PickupControl::pickupHit(unsigned id)
{
    if (id < pickup_states.size())
    {
        std::vector<PickupState>::iterator it = pickup_states.begin() + id;
        if (it->state == PU_INACTIVE)
        {
            Pickup *p = pickups->at(id);
            p->apply(player);
            
            PowerUp *pu = dynamic_cast<PowerUp*>(p);
            if (pu) {
                it->state = PU_ACTIVE;
                active_pickups.push_back(id);
                it->update_time = time + pu->active_time;
            } else {
                it->state = PU_EXPIRED;
            }
            
            // TODO: set entity to invisible if this is the main player
        }
    }
}
/*
int PickupControl::userBegin()
{   
    OgreNewt::Body *ball_body, *pickup_body;
    if (m_body0->getType() % BODY_TYPE_COUNT == BT_BALL) 
    {
        ball_body = m_body0;
        pickup_body = m_body1;
    }
    else if (m_body1->getType() % BODY_TYPE_COUNT == BT_BALL) 
    {
        ball_body = m_body1;
        pickup_body = m_body0;
    }
    
    unsigned pickup_id = (unsigned)pickup_body->getUserData();
    
    Ball *ball = (Ball *)ball_body->getUserData();
    ball->getPlayer()->getPickupControl()->pickupHit(pickup_id);
        
    return 0;
}
*/

void PickupControl::setPlayState(PlayState *ps)
{
    std::vector<Pickup*>::iterator i;
    for(i = pickups->begin(); i != pickups->end(); ++i)
        (*i)->setPlayState(ps);
}

PickupControl* PickupControl::clone(void) {
    return new PickupControl(pickups, world);
}
